using Microsoft.Phone.Controls;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
namespace MicroMsg.UI.UserContrl
{
	public class MMTiltEffect : DependencyObject
	{
		private class LogarithmicEase : EasingFunctionBase
		{
			protected override double EaseInCore(double normalizedTime)
			{
				return Math.Log(normalizedTime + 1.0) / 0.693147181;
			}
		}
		private const double MaxAngle = 0.3;
		private const double MaxDepression = 25.0;
		private static Dictionary<DependencyObject, CacheMode> _originalCacheMode;
		private static readonly TimeSpan TiltReturnAnimationDelay;
		private static readonly TimeSpan TiltReturnAnimationDuration;
		private static FrameworkElement currentTiltElement;
		private static Storyboard tiltReturnStoryboard;
		private static DoubleAnimation tiltReturnXAnimation;
		private static DoubleAnimation tiltReturnYAnimation;
		private static DoubleAnimation tiltReturnZAnimation;
		private static Point currentTiltElementCenter;
		private static bool wasPauseAnimation;
		public static readonly DependencyProperty IsTiltEnabledProperty;
		public static readonly DependencyProperty SuppressTiltProperty;
		public static bool UseLogarithmicEase
		{
			get;
			set;
		}
		public static List<Type> TiltableItems
		{
			get;
			private set;
		}
		private MMTiltEffect()
		{
		}
		static MMTiltEffect()
		{
			MMTiltEffect._originalCacheMode = new Dictionary<DependencyObject, CacheMode>();
			MMTiltEffect.TiltReturnAnimationDelay = TimeSpan.FromMilliseconds(200.0);
			MMTiltEffect.TiltReturnAnimationDuration = TimeSpan.FromMilliseconds(100.0);
			MMTiltEffect.wasPauseAnimation = false;
			MMTiltEffect.IsTiltEnabledProperty = DependencyProperty.RegisterAttached("IsTiltEnabled", typeof(bool), typeof(MMTiltEffect), new PropertyMetadata(new PropertyChangedCallback(MMTiltEffect.OnIsTiltEnabledChanged)));
			MMTiltEffect.SuppressTiltProperty = DependencyProperty.RegisterAttached("SuppressTilt", typeof(bool), typeof(MMTiltEffect), null);
			List<Type> list = new List<Type>();
			list.Add(typeof(ButtonBase));
			list.Add(typeof(ListBoxItem));
			list.Add(typeof(MenuItem));
			list.Add(typeof(Image));
			MMTiltEffect.TiltableItems = list;
		}
		public static bool GetIsTiltEnabled(DependencyObject source)
		{
			return (bool)source.GetValue(MMTiltEffect.IsTiltEnabledProperty);
		}
		public static void SetIsTiltEnabled(DependencyObject source, bool value)
		{
			source.SetValue(MMTiltEffect.IsTiltEnabledProperty, value);
		}
		public static bool GetSuppressTilt(DependencyObject source)
		{
			return (bool)source.GetValue(MMTiltEffect.SuppressTiltProperty);
		}
		public static void SetSuppressTilt(DependencyObject source, bool value)
		{
			source.SetValue(MMTiltEffect.SuppressTiltProperty, value);
		}
		private static void OnIsTiltEnabledChanged(DependencyObject target, DependencyPropertyChangedEventArgs args)
		{
			FrameworkElement frameworkElement = target as FrameworkElement;
			if (frameworkElement != null)
			{
				if ((bool)args.get_NewValue())
				{
					frameworkElement.add_ManipulationStarted(new EventHandler<ManipulationStartedEventArgs>(MMTiltEffect.TiltEffect_ManipulationStarted));
					return;
				}
				frameworkElement.remove_ManipulationStarted(new EventHandler<ManipulationStartedEventArgs>(MMTiltEffect.TiltEffect_ManipulationStarted));
			}
		}
		private static void TiltEffect_ManipulationStarted(object sender, ManipulationStartedEventArgs e)
		{
			MMTiltEffect.TryStartTiltEffect(sender as FrameworkElement, e);
		}
		private static void TiltEffect_ManipulationDelta(object sender, ManipulationDeltaEventArgs e)
		{
			MMTiltEffect.ContinueTiltEffect(sender as FrameworkElement, e);
		}
		private static void TiltEffect_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e)
		{
			MMTiltEffect.EndTiltEffect(MMTiltEffect.currentTiltElement);
		}
		private static void TryStartTiltEffect(FrameworkElement source, ManipulationStartedEventArgs manipulationStartedEventArgs_0)
		{
			using (IEnumerator<FrameworkElement> enumerator = (manipulationStartedEventArgs_0.get_OriginalSource() as FrameworkElement).GetVisualAncestors().GetEnumerator())
			{
				while (enumerator.MoveNext())
				{
					FrameworkElement current = enumerator.get_Current();
					using (List<Type>.Enumerator enumerator2 = MMTiltEffect.TiltableItems.GetEnumerator())
					{
						while (enumerator2.MoveNext())
						{
							Type current2 = enumerator2.get_Current();
							if (current2.IsAssignableFrom(current.GetType()))
							{
								FrameworkElement frameworkElement;
								if (current.ReadLocalValue(MMTiltEffect.SuppressTiltProperty) is bool)
								{
									frameworkElement = current;
								}
								else
								{
									frameworkElement = Enumerable.FirstOrDefault<FrameworkElement>(current.GetVisualAncestors(), (FrameworkElement frameworkElement_0) => frameworkElement_0.ReadLocalValue(MMTiltEffect.SuppressTiltProperty) is bool);
								}
								if (frameworkElement == null || !(bool)frameworkElement.ReadLocalValue(MMTiltEffect.SuppressTiltProperty))
								{
									FrameworkElement frameworkElement2 = VisualTreeHelper.GetChild(current, 0) as FrameworkElement;
									FrameworkElement frameworkElement3 = manipulationStartedEventArgs_0.get_ManipulationContainer() as FrameworkElement;
									if (frameworkElement2 != null && frameworkElement3 != null)
									{
										Point touchPoint = frameworkElement3.TransformToVisual(frameworkElement2).Transform(manipulationStartedEventArgs_0.get_ManipulationOrigin());
										Point centerPoint = new Point(frameworkElement2.get_ActualWidth() / 2.0, frameworkElement2.get_ActualHeight() / 2.0);
										Point centerToCenterDelta = MMTiltEffect.GetCenterToCenterDelta(frameworkElement2, source);
										MMTiltEffect.BeginTiltEffect(frameworkElement2, touchPoint, centerPoint, centerToCenterDelta);
										return;
									}
									return;
								}
							}
						}
					}
				}
			}
		}
		private static Point GetCenterToCenterDelta(FrameworkElement element, FrameworkElement container)
		{
			Point point = new Point(element.get_ActualWidth() / 2.0, element.get_ActualHeight() / 2.0);
			PhoneApplicationFrame phoneApplicationFrame = container as PhoneApplicationFrame;
			Point point2;
			if (phoneApplicationFrame != null)
			{
				if ((phoneApplicationFrame.get_Orientation() & 2) == 2)
				{
					point2 = new Point(container.get_ActualHeight() / 2.0, container.get_ActualWidth() / 2.0);
				}
				else
				{
					point2 = new Point(container.get_ActualWidth() / 2.0, container.get_ActualHeight() / 2.0);
				}
			}
			else
			{
				point2 = new Point(container.get_ActualWidth() / 2.0, container.get_ActualHeight() / 2.0);
			}
			Point point3 = element.TransformToVisual(container).Transform(point);
			Point result = new Point(point2.get_X() - point3.get_X(), point2.get_Y() - point3.get_Y());
			return result;
		}
		private static void BeginTiltEffect(FrameworkElement element, Point touchPoint, Point centerPoint, Point centerDelta)
		{
			if (MMTiltEffect.tiltReturnStoryboard != null)
			{
				MMTiltEffect.StopTiltReturnStoryboardAndCleanup();
			}
			if (!MMTiltEffect.PrepareControlForTilt(element, centerDelta))
			{
				return;
			}
			MMTiltEffect.currentTiltElement = element;
			MMTiltEffect.currentTiltElementCenter = centerPoint;
			MMTiltEffect.PrepareTiltReturnStoryboard(element);
			MMTiltEffect.ApplyTiltEffect(MMTiltEffect.currentTiltElement, touchPoint, MMTiltEffect.currentTiltElementCenter);
		}
		private static bool PrepareControlForTilt(FrameworkElement element, Point centerDelta)
		{
			if (element.get_Projection() == null)
			{
				if (element.get_RenderTransform() == null || element.get_RenderTransform().GetType() == typeof(MatrixTransform))
				{
					MMTiltEffect._originalCacheMode.set_Item(element, element.get_CacheMode());
					element.set_CacheMode(null);
					TranslateTransform translateTransform = new TranslateTransform();
					translateTransform.set_X(centerDelta.get_X());
					translateTransform.set_Y(centerDelta.get_Y());
					element.set_RenderTransform(translateTransform);
					PlaneProjection planeProjection = new PlaneProjection();
					planeProjection.set_GlobalOffsetX(-1.0 * centerDelta.get_X());
					planeProjection.set_GlobalOffsetY(-1.0 * centerDelta.get_Y());
					element.set_Projection(planeProjection);
					element.add_ManipulationDelta(new EventHandler<ManipulationDeltaEventArgs>(MMTiltEffect.TiltEffect_ManipulationDelta));
					element.add_ManipulationCompleted(new EventHandler<ManipulationCompletedEventArgs>(MMTiltEffect.TiltEffect_ManipulationCompleted));
					return true;
				}
			}
			return false;
		}
		private static void RevertPrepareControlForTilt(FrameworkElement element)
		{
			element.remove_ManipulationDelta(new EventHandler<ManipulationDeltaEventArgs>(MMTiltEffect.TiltEffect_ManipulationDelta));
			element.remove_ManipulationCompleted(new EventHandler<ManipulationCompletedEventArgs>(MMTiltEffect.TiltEffect_ManipulationCompleted));
			element.set_Projection(null);
			element.set_RenderTransform(null);
			CacheMode cacheMode;
			if (MMTiltEffect._originalCacheMode.TryGetValue(element, ref cacheMode))
			{
				element.set_CacheMode(cacheMode);
				MMTiltEffect._originalCacheMode.Remove(element);
				return;
			}
			element.set_CacheMode(null);
		}
		private static void PrepareTiltReturnStoryboard(FrameworkElement element)
		{
			if (MMTiltEffect.tiltReturnStoryboard == null)
			{
				MMTiltEffect.tiltReturnStoryboard = new Storyboard();
				MMTiltEffect.tiltReturnStoryboard.add_Completed(new EventHandler(MMTiltEffect.TiltReturnStoryboard_Completed));
				MMTiltEffect.tiltReturnXAnimation = new DoubleAnimation();
				Storyboard.SetTargetProperty(MMTiltEffect.tiltReturnXAnimation, new PropertyPath(PlaneProjection.RotationXProperty));
				MMTiltEffect.tiltReturnXAnimation.set_BeginTime(new TimeSpan?(MMTiltEffect.TiltReturnAnimationDelay));
				MMTiltEffect.tiltReturnXAnimation.set_To(new double?(0.0));
				MMTiltEffect.tiltReturnXAnimation.set_Duration(MMTiltEffect.TiltReturnAnimationDuration);
				MMTiltEffect.tiltReturnYAnimation = new DoubleAnimation();
				Storyboard.SetTargetProperty(MMTiltEffect.tiltReturnYAnimation, new PropertyPath(PlaneProjection.RotationYProperty));
				MMTiltEffect.tiltReturnYAnimation.set_BeginTime(new TimeSpan?(MMTiltEffect.TiltReturnAnimationDelay));
				MMTiltEffect.tiltReturnYAnimation.set_To(new double?(0.0));
				MMTiltEffect.tiltReturnYAnimation.set_Duration(MMTiltEffect.TiltReturnAnimationDuration);
				MMTiltEffect.tiltReturnZAnimation = new DoubleAnimation();
				Storyboard.SetTargetProperty(MMTiltEffect.tiltReturnZAnimation, new PropertyPath(PlaneProjection.GlobalOffsetZProperty));
				MMTiltEffect.tiltReturnZAnimation.set_BeginTime(new TimeSpan?(MMTiltEffect.TiltReturnAnimationDelay));
				MMTiltEffect.tiltReturnZAnimation.set_To(new double?(0.0));
				MMTiltEffect.tiltReturnZAnimation.set_Duration(MMTiltEffect.TiltReturnAnimationDuration);
				if (MMTiltEffect.UseLogarithmicEase)
				{
					MMTiltEffect.tiltReturnXAnimation.set_EasingFunction(new MMTiltEffect.LogarithmicEase());
					MMTiltEffect.tiltReturnYAnimation.set_EasingFunction(new MMTiltEffect.LogarithmicEase());
					MMTiltEffect.tiltReturnZAnimation.set_EasingFunction(new MMTiltEffect.LogarithmicEase());
				}
				MMTiltEffect.tiltReturnStoryboard.get_Children().Add(MMTiltEffect.tiltReturnXAnimation);
				MMTiltEffect.tiltReturnStoryboard.get_Children().Add(MMTiltEffect.tiltReturnYAnimation);
				MMTiltEffect.tiltReturnStoryboard.get_Children().Add(MMTiltEffect.tiltReturnZAnimation);
			}
			Storyboard.SetTarget(MMTiltEffect.tiltReturnXAnimation, element.get_Projection());
			Storyboard.SetTarget(MMTiltEffect.tiltReturnYAnimation, element.get_Projection());
			Storyboard.SetTarget(MMTiltEffect.tiltReturnZAnimation, element.get_Projection());
		}
		private static void ContinueTiltEffect(FrameworkElement element, ManipulationDeltaEventArgs manipulationDeltaEventArgs_0)
		{
			FrameworkElement frameworkElement = manipulationDeltaEventArgs_0.get_ManipulationContainer() as FrameworkElement;
			if (frameworkElement == null || element == null)
			{
				return;
			}
			Point point = frameworkElement.TransformToVisual(element).Transform(manipulationDeltaEventArgs_0.get_ManipulationOrigin());
			if (!new Rect(0.0, 0.0, MMTiltEffect.currentTiltElement.get_ActualWidth(), MMTiltEffect.currentTiltElement.get_ActualHeight()).Contains(point))
			{
				MMTiltEffect.PauseTiltEffect();
				return;
			}
			MMTiltEffect.ApplyTiltEffect(MMTiltEffect.currentTiltElement, manipulationDeltaEventArgs_0.get_ManipulationOrigin(), MMTiltEffect.currentTiltElementCenter);
		}
		private static void EndTiltEffect(FrameworkElement element)
		{
			if (element != null)
			{
				element.remove_ManipulationCompleted(new EventHandler<ManipulationCompletedEventArgs>(MMTiltEffect.TiltEffect_ManipulationCompleted));
				element.remove_ManipulationDelta(new EventHandler<ManipulationDeltaEventArgs>(MMTiltEffect.TiltEffect_ManipulationDelta));
			}
			if (MMTiltEffect.tiltReturnStoryboard != null)
			{
				MMTiltEffect.wasPauseAnimation = false;
				if (MMTiltEffect.tiltReturnStoryboard.GetCurrentState() != null)
				{
					MMTiltEffect.tiltReturnStoryboard.Begin();
					return;
				}
			}
			else
			{
				MMTiltEffect.StopTiltReturnStoryboardAndCleanup();
			}
		}
		private static void TiltReturnStoryboard_Completed(object sender, EventArgs e)
		{
			if (MMTiltEffect.wasPauseAnimation)
			{
				MMTiltEffect.ResetTiltEffect(MMTiltEffect.currentTiltElement);
				return;
			}
			MMTiltEffect.StopTiltReturnStoryboardAndCleanup();
		}
		private static void ResetTiltEffect(FrameworkElement element)
		{
			PlaneProjection planeProjection = element.get_Projection() as PlaneProjection;
			planeProjection.set_RotationY(0.0);
			planeProjection.set_RotationX(0.0);
			planeProjection.set_GlobalOffsetZ(0.0);
		}
		private static void StopTiltReturnStoryboardAndCleanup()
		{
			if (MMTiltEffect.tiltReturnStoryboard != null)
			{
				MMTiltEffect.tiltReturnStoryboard.Stop();
			}
			MMTiltEffect.RevertPrepareControlForTilt(MMTiltEffect.currentTiltElement);
		}
		private static void PauseTiltEffect()
		{
			if (MMTiltEffect.tiltReturnStoryboard != null && !MMTiltEffect.wasPauseAnimation)
			{
				MMTiltEffect.tiltReturnStoryboard.Stop();
				MMTiltEffect.wasPauseAnimation = true;
				MMTiltEffect.tiltReturnStoryboard.Begin();
			}
		}
		private static void ResetTiltReturnStoryboard()
		{
			MMTiltEffect.tiltReturnStoryboard.Stop();
			MMTiltEffect.wasPauseAnimation = false;
		}
		private static void ApplyTiltEffect(FrameworkElement element, Point touchPoint, Point centerPoint)
		{
			MMTiltEffect.ResetTiltReturnStoryboard();
			Point point = new Point(Math.Min(Math.Max(touchPoint.get_X() / (centerPoint.get_X() * 2.0), 0.0), 1.0), Math.Min(Math.Max(touchPoint.get_Y() / (centerPoint.get_Y() * 2.0), 0.0), 1.0));
			double num = Math.Abs(point.get_X() - 0.5);
			double num2 = Math.Abs(point.get_Y() - 0.5);
			double num3 = (double)(-(double)Math.Sign(point.get_X() - 0.5));
			double num4 = (double)Math.Sign(point.get_Y() - 0.5);
			double num5 = num + num2;
			double num6 = (num + num2 > 0.0) ? (num / (num + num2)) : 0.0;
			double num7 = num5 * 0.3 * 180.0 / 3.1415926535897931;
			double num8 = (1.0 - num5) * 25.0;
			if (element.get_ActualHeight() < 100.0 && element.get_ActualWidth() < 100.0)
			{
				num7 *= 5.0;
				num8 *= 8.0;
				if (num7 > 60.0)
				{
					num7 = 60.0;
				}
				if (num7 < 30.0)
				{
					num8 *= 2.0;
				}
			}
			else
			{
				if (element.get_ActualHeight() < 200.0 && element.get_ActualWidth() < 200.0)
				{
					num7 *= 3.0;
					if (num7 > 60.0)
					{
						num7 = 60.0;
					}
					num8 *= 2.0;
					if (num7 < 15.0)
					{
						num8 *= 4.0;
					}
				}
				else
				{
					if (element.get_ActualHeight() < 300.0 && element.get_ActualWidth() < 300.0)
					{
						num7 *= 1.5;
						if (num7 > 60.0)
						{
							num7 = 60.0;
						}
						num8 *= 2.0;
						if (num7 < 7.0)
						{
							num8 *= 2.0;
						}
					}
					else
					{
						if (num7 < 7.0)
						{
							num8 *= 2.0;
						}
					}
				}
			}
			PlaneProjection planeProjection = element.get_Projection() as PlaneProjection;
			planeProjection.set_RotationY(num7 * num6 * num3);
			planeProjection.set_RotationX(num7 * (1.0 - num6) * num4);
			planeProjection.set_GlobalOffsetZ(-num8);
		}
	}
}
